﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Runtime.Serialization;

namespace WcfCore
{
	public class PreserveObjectReferencesDataContractOperationBehavior : DataContractSerializerOperationBehavior
	{
		public PreserveObjectReferencesDataContractOperationBehavior(OperationDescription operationDescription)
			: base(operationDescription) { }

		public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
		{
			return CreateDataContractSerializer(type, name, ns, knownTypes);
		}

		private static XmlObjectSerializer CreateDataContractSerializer(Type type, string name, string ns, IList<Type> knownTypes)
		{
			return CreateDataContractSerializer(type, name, ns, knownTypes);
		}

		public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
		{
			return new DataContractSerializer(type, name, ns, knownTypes, int.MaxValue, false,
				true /* preserveObjectReferences */,
				null);
		}
	}

	public class PreserveObjectReferencesDataContractSerializerFormatAttribute : Attribute, IOperationBehavior
	{
		public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { }

		public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
		{
			IOperationBehavior innerBehavior = new PreserveObjectReferencesDataContractOperationBehavior(description);
			innerBehavior.ApplyClientBehavior(description, proxy);
		}

		public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
		{
			IOperationBehavior innerBehavior = new PreserveObjectReferencesDataContractOperationBehavior(description);
			innerBehavior.ApplyDispatchBehavior(description, dispatch);
		}

		public void Validate(OperationDescription description) { }
	}
}
